package com.xc.controller;

import com.xc.util.AjaxResponse;
import com.xc.util.GlobalConfig;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipInputStream;

@RestController
@RequestMapping("/processDefinition")
public class ProcessDefinitionController {

    @Autowired
    private RepositoryService repositoryService;

    /**
     * 通过上传 BPMN 文件，进行添加流程定义
     * @param file
     * @param processName 流程定义名称
     * @return
     */
    @PostMapping(value = "/uploadStreamAndDeployment")
    public AjaxResponse uploadStreamAndDeployment(@RequestParam("processFile")MultipartFile file,String processName){
        // 获取上传的文件名
        String fileName = file.getOriginalFilename();
        try{
            // 文件的扩展名
            String extension = FilenameUtils.getExtension(fileName);
            // 得到输入流（字节流）对象
            InputStream inputStream = file.getInputStream();
            Deployment deployment = null;
            if (extension.equals("zip")){
                ZipInputStream zipFile = new ZipInputStream(inputStream);
                deployment = repositoryService.createDeployment() // 初始化部署流程
                        .addZipInputStream(zipFile)
                        //.name("部署流程")
                        .name(processName)
                        .deploy();
            }else{
                deployment = repositoryService.createDeployment()
                        .addInputStream(fileName,inputStream)
                        .name(processName)
                        .deploy();
            }
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), deployment.getId()+";"+fileName);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "上传部署流程定义失败", e.toString());
        }
    }

    /**
     * 通过 BPMNjs生成 xml 字符串提交，进行添加流程定义
     * @return
     */
    @PostMapping(value = "/upload")
    public AjaxResponse upload(@RequestParam("stringBPMN") String stringBPMN, String processName){
        try{
            Deployment deployment = repositoryService.createDeployment()
                    .addString("CreateWidthBPMNJS.bpmn", stringBPMN)
                    .name(processName)
                    .deploy();
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), deployment.getId());
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "string部署流程定义失败", e.toString());
        }
    }

    /**
     * 获取流程定义列表
     * @return
     */
    @GetMapping(value = "/getDefinitions")
    public AjaxResponse getDefinitions() {
        try{
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
            List<HashMap<String, Object>> listMap= new ArrayList<HashMap<String, Object>>();
            for (ProcessDefinition pd : list) {
                HashMap<String, Object> hashMap = new HashMap<>();
                //System.out.println("流程定义ID："+pd.getId());
                hashMap.put("processDefinitionID", pd.getId());
                hashMap.put("name", pd.getName());
                hashMap.put("key", pd.getKey());
                hashMap.put("resourceName", pd.getResourceName());
                hashMap.put("deploymentID", pd.getDeploymentId());
                hashMap.put("version", pd.getVersion());
                listMap.add(hashMap);
            }
            list.sort((x,y) -> y.getVersion() - x.getVersion());
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), list);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取流程定义失败", e.toString());
        }
    }

    /**
     * 获取流程定义xml
     * @param deploymentFileUUID
     * @return
     */
    @PostMapping(value = "/addDeploymentByFileNameBPMN")
    public void addDeploymentByFileNameBPMN(@RequestParam("deploymentFileUUID") String deploymentFileUUID, @RequestParam("resourceName") String resourceName, HttpServletResponse response) {
        try{
            InputStream inputStream = repositoryService.getResourceAsStream(deploymentFileUUID, resourceName);
            byte[] bytes = new byte[inputStream.available()];
            response.setContentType("text/xml");
            ServletOutputStream outputStream = response.getOutputStream();
            while (inputStream.read(bytes) != -1){
                outputStream.write(bytes);
            }
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 删除流程定义
     * @param pdID
     * @return
     */
    @GetMapping(value = "/delDefinition")
    public AjaxResponse delDefinition( @RequestParam("pdID") String pdID){
        try{
            repositoryService.deleteDeployment(pdID,true);
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "删除流程定义", e.toString());
        }
    }


    /**
     * 获取流程部署列表
     * @return
     */
    @GetMapping(value = "/getDeployments")
    public AjaxResponse getDeployments() {
        try{
            List<Deployment> list = repositoryService.createDeploymentQuery().list();
            List<HashMap<String, Object>> listMap= new ArrayList<HashMap<String, Object>>();
            for (Deployment dep : list) {
                HashMap<String, Object> hashMap = new HashMap<>();
                //System.out.println("流程定义ID："+pd.getId());
                hashMap.put("id", dep.getId());
                hashMap.put("name", dep.getName());
                hashMap.put("deploymentTime", dep.getDeploymentTime());
                listMap.add(hashMap);
            }
            list.sort((x,y) -> y.getVersion() - x.getVersion());
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), listMap);
        }catch (Exception e){
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取流程部署列表", e.toString());
        }
    }
}
